package jmine.tec.web.wicket.component.table;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jmine.tec.report.api.ReportElement;
import jmine.tec.report.api.table.ReportCell;
import jmine.tec.report.api.table.ReportRow;
import jmine.tec.report.api.table.ReportTable;
import jmine.tec.report.impl.table.ReportCellImpl;
import jmine.tec.web.wicket.component.CheckGroup;
import jmine.tec.web.wicket.component.InlinedCheck;
import jmine.tec.web.wicket.component.InlinedCheckGroupSelector;
import jmine.tec.web.wicket.component.command.TableCommandsProvider;
import jmine.tec.web.wicket.component.command.button.SearchCommandHandler;

import org.apache.wicket.behavior.SimpleAttributeModifier;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.DataGridView;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Check;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.IModel;

/**
 * {@link SearchResultAjaxSelectionTableBuilder} para criar o markup de um Report
 * 
 * @author Rafael Volpato
 * @param <BO> tipo da entidade
 */
public class SearchResultSelectionTableBuilder<BO> extends SearchResultTableBuilder<BO> {

    private static final double SELECT_COLUMN_WIDTH = 0.1;

    private final Set<Serializable> chosen;

    private final List<Check<SelectEntityModel>> checkboxes;

    private CheckGroup checkGroup;

    private Boolean selectAll = Boolean.FALSE;

    /**
     * Construtor.
     * 
     * @param targetClass targetClass
     * @param searchHandler {@link SearchCommandHandler}
     * @param commandsProvider {@link TableCommandsProvider}
     * @param chosen armazena os elementos que foram selecionados
     */
    public SearchResultSelectionTableBuilder(Class<BO> targetClass, SearchCommandHandler<BO> searchHandler,
            TableCommandsProvider commandsProvider, Set<Serializable> chosen) {
        super(targetClass, searchHandler, commandsProvider);
        this.chosen = chosen;
        this.checkboxes = new ArrayList<Check<SelectEntityModel>>();
    }

    /**
     * @return the selectAll
     */
    public Boolean getSelectAll() {
        return this.selectAll;
    }

    /**
     * @param selectAll the selectAll to set
     */
    public void setSelectAll(Boolean selectAll) {
        this.selectAll = selectAll;
    }

    /**
     * @return the {@link CheckGroup}
     */
    public CheckGroup getCheckGroup() {
        if (this.checkGroup == null) {
            this.checkGroup = new CheckGroup("selectionGroup", this.chosen, this.checkboxes);
        }
        return this.checkGroup;
    }

    /**
     * cria uma lista com {@link ICellPopulator} para as linhas da tabela
     * 
     * @param table {@link ReportTable}
     * @return {@link List}
     */
    @Override
    @SuppressWarnings("unchecked")
    protected List<ICellPopulator<ReportRow>> getCellPopulators(ReportTable table) {
        List<ICellPopulator<ReportRow>> cellPopulators = super.getCellPopulators(table);

        ICellPopulator checkboxCellPopulator = new ICellPopulator<ReportRow>() {
            public void detach() {
            }

            public void populateItem(Item<ICellPopulator<ReportRow>> cellItem, String componentId, IModel<ReportRow> rowModel) {
                Map<String, ReportCell> cellMap = rowModel.getObject().getCellMap();
                ReportCell cellValue = cellMap.get("pk");
                Long pk = Long.valueOf(String.valueOf(cellValue.getValue()));
                SelectEntityModel checkModel = new SelectEntityModel(SearchResultSelectionTableBuilder.this.chosen, pk);
                InlinedCheck checkBox = new InlinedCheck(componentId, checkModel, SearchResultSelectionTableBuilder.this.getCheckGroup());
                SearchResultSelectionTableBuilder.this.checkboxes.add(checkBox.getCheck());
                cellItem.add(checkBox);
            }
        };
        cellPopulators.add(0, checkboxCellPopulator);

        return cellPopulators;
    }

    /**
     * Cria um header
     * 
     * @param reportElement {@link ReportTable}
     * @return {@link ListView}
     */
    @Override
    protected ListView<ReportCell> createColumnHeader(ReportTable reportElement) {
        ListView<ReportCell> lvCells = super.createColumnHeader(reportElement);
        List<ReportCell> reportCells = lvCells.getModelObject();
        ReportCellImpl reportCellImpl = new ReportCellImpl("selectionBox");
        this.createRPI(reportCellImpl).setRelativeWidth(SELECT_COLUMN_WIDTH);
        reportCells.add(0, reportCellImpl);
        lvCells.setModelObject(reportCells);
        return lvCells;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected ListView<ReportCell> doCreateHeaderListView(List<ReportCell> header) {
        final double totalWidth = this.sumRelativeWidth(header);

        return new ListView<ReportCell>("columns", header) {
            @Override
            protected void populateItem(ListItem<ReportCell> item) {
                ReportCell reportCell = item.getModelObject();
                String cellValue = SearchResultSelectionTableBuilder.this.renderReportCell(reportCell);

                if ("selectionBox".equals(cellValue)) {
                    item.add(new InlinedCheckGroupSelector("cell", SearchResultSelectionTableBuilder.this.getCheckGroup()));

                } else {
                    Label cell = new Label("cell", cellValue);
                    String widthCell = SearchResultSelectionTableBuilder.this.widthCalculate(reportCell, totalWidth);
                    cell.add(new SimpleAttributeModifier("width", widthCell));
                    item.add(cell);
                }
            }
        };
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected DataGridView<ReportRow> createAndAddBody(ListItem<ReportElement> item, ReportTable<?> table) {
        DataGridView<ReportRow> dataGridView = super.createAndAddBody(item, table);
        item.add(this.getCheckGroup());
        return dataGridView;
    }
}
